package com.fastloan.mgt.application.base.util;

import com.fastloan.mgt.application.approve.model.vo.ApplicationApproveHistoryVO;
import com.fastloan.mgt.application.base.model.ApplicationIPC;
import com.fastloan.mgt.application.base.model.ApplicationPdfInfo;
import com.fastloan.mgt.application.base.model.ApplicationValueModifyHistory;
import com.fastloan.mgt.application.base.model.ApplicationVo;
import com.fastloan.mgt.application.contract.model.ApplicationContract;
import com.fastloan.mgt.application.phoneapprove.model.ApplicationPhoneApprove;
import com.fastloan.mgt.product.basics.model.Product;
import com.fastloan.utils.DateTimeUtil;
import com.itextpdf.kernel.color.DeviceRgb;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.draw.DottedLine;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.Style;
import com.itextpdf.layout.border.Border;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TabAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;
import com.kawins.util.IDCardUtil;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static com.fastloan.mgt.application.phoneapprove.service.impl.ApplicationPhoneApproveServiceImpl.PASS;
import static com.fastloan.utils.DateTimeUtil.NORM_DATETIME_PATTERN;

/**
 * @author yanwe
 * createTime 2017-11-2017/11/29 14:43
 */
public class ApplicationPDF {

    private static UnitValue [] infoUnitValue = UnitValue.createPercentArray(new float[]{23,27,23,27});
    private static UnitValue [] phoneApproveUnitValue = UnitValue.createPercentArray(new float[]{1,1,1,1});
    private static UnitValue [] expertAuditUnitValue = UnitValue.createPercentArray(new float[]{1,1,1,1,1});

    public static void createPdf(ApplicationPdfInfo applicationPdfInfo, OutputStream outputStream) throws IOException {
        PdfDocument pdf = new PdfDocument(new PdfWriter(outputStream));
        pdf.setDefaultPageSize(PageSize.A4);
        Document document = new Document(pdf);
        document.setFont(getPdfFont());

        //标题
        Paragraph title = new Paragraph(new Text("进件"+applicationPdfInfo.getApplication()
                .getApplicationCode()+"详情").addStyle(getBoldFont()));
        title.setTextAlignment(TextAlignment.CENTER);
        document.add(title);

        //空行
        Paragraph blankRow = new Paragraph();
        document.add(blankRow);

        //申请信息
        createApplyInfoModule(document, applicationPdfInfo.getApplication());

        //创建签约模块
        createContractModule(document, applicationPdfInfo.getApplicationContract());

        //创建产品信息
        createProductModule(document, applicationPdfInfo.getProduct());

        //客户信息IPC
        createFinalIPCTable(applicationPdfInfo.getCustomerIPC(),"客户信息", document);

        //客户经理调查IPC
        createFinalIPCTable(applicationPdfInfo.getCustomerManagerIPC(),"客户经理调查", document);

        //创建电核模块
        createPhoneApproveModule(document, applicationPdfInfo.getApplicationPhoneApprove());

        //创建专家审批模块
        createExpertApproveModule(document, applicationPdfInfo.getExpertApproveList());
        document.close();
    }

    private static void createApplyInfoModule(Document document, ApplicationVo application) {
        if (application == null){
            return;
        }
        createInfoTableTitle(document,"申请信息");
        Table applyInfoTable = createInfoTable();
        applyInfoTable.addCell(noBorderCell("姓名:")).addCell(noBorderCell(application.getCname()));
        applyInfoTable.addCell(noBorderCell("性别:")).addCell(noBorderCell(IDCardUtil
                .getSexByIDCard(application.getCardNum()).getSexSrt()));
        applyInfoTable.addCell(noBorderCell("身份证:")).addCell(noBorderCell(application.getCardNum()));
        applyInfoTable.addCell(noBorderCell("申请金额(元):")).addCell(noBorderCell(application.getApplyAmount()));
        applyInfoTable.addCell(noBorderCell("申请期限(月):")).addCell(noBorderCell(application.getApplyPeriod()));
        applyInfoTable.addCell(noBorderCell("手机号:")).addCell(noBorderCell(application.getPhoneNum()));
        applyInfoTable.addCell(noBorderCell("进件编号:")).addCell(noBorderCell(application.getApplicationCode()));
        applyInfoTable.addCell(noBorderCell("客户经理:")).addCell(noBorderCell(application.getCustomerManagerName()));
        document.add(applyInfoTable);
    }

    private static void createContractModule(Document document, ApplicationContract applicationContract) {
        if (applicationContract == null){
            return;
        }
        createInfoTableTitle(document,"签约信息");
        Table contractTable = createInfoTable();
        contractTable.addCell(noBorderCell("放款金额:")).addCell(noBorderCell(applicationContract.getLoanAmount()));
        contractTable.addCell(noBorderCell("合同编号:")).addCell(noBorderCell(applicationContract.getContractNo()));
        contractTable.addCell(noBorderCell("放款月利率(%):")).addCell(noBorderCell(applicationContract.getLoanMonthRate()));
        contractTable.addCell(noBorderCell("期限(月):")).addCell(noBorderCell(applicationContract.getCreditPeriod()));
        contractTable.addCell(noBorderCell("罚息(%):")).addCell(noBorderCell(applicationContract.getDefaultInterest()));
        contractTable.addCell(noBorderCell("放款帐号:")).addCell(noBorderCell(applicationContract.getLoanAccount()));
        contractTable.addCell(noBorderCell("用途:")).addCell(noBorderCell(applicationContract.getPurpose()));
        contractTable.addCell(noBorderCell("放款时间:")).addCell(noBorderCell(DateTimeUtil
                .format(applicationContract.getLoanTime(),NORM_DATETIME_PATTERN)));
        document.add(contractTable);
    }

    private static void createProductModule(Document document, Product product) {
        if (product == null){
            return;
        }
        createInfoTableTitle(document,"产品信息");
        Table productTable = createInfoTable();
        productTable.addCell(noBorderCell("产品名称:")).addCell(noBorderCell(product.getProductName()));
        productTable.addCell(noBorderCell("调查类型:")).addCell(noBorderCell(
                (product.getSurveyType() == 1 ? "线下" : "线上") + "调查"));
        productTable.addCell(noBorderCell("还款方式:")).addCell(noBorderCell(getRepayment(product.getRepayment())));
        productTable.addCell(noBorderCell("产品额度区间(元):")).addCell(noBorderCell(obj2str(product.getSpendingFloor())
                +"~"+obj2str(product.getSpendingLimit())));
        productTable.addCell(noBorderCell("产品月利率区间(%):")).addCell(noBorderCell(obj2str(product.getMonthlyFloor())
                +"~"+obj2str(product.getMonthlyLimit())));
        productTable.addCell(noBorderCell("产品期限区间(月):")).addCell(noBorderCell(obj2str(product.getTimeFloor())
                +"~"+obj2str(product.getTimeLimit())));
        document.add(productTable);
    }

    private static void createExpertApproveModule(Document document, List<ApplicationApproveHistoryVO> expertApproveList) {
        if (expertApproveList == null || expertApproveList.isEmpty()){
            return;
        }
        createInfoTableTitle(document,"专家审批");
        Table expertAuditTable = createSmallCustomCellTable(expertAuditUnitValue);
        expertAuditTable.addCell(tableTitle("审批人"))
                .addCell(tableTitle("审批决定"))
                .addCell(tableTitle("审批额度"))
                .addCell(tableTitle("审批月利率"))
                .addCell(tableTitle("审批时间"));
        for (ApplicationApproveHistoryVO expertApprove : expertApproveList) {
            expertAuditTable
                    .addCell(smallCell(expertApprove.getApproveUserName()))
                    .addCell(smallCell(getApproveStatus(expertApprove.getApproveStatus())))
                    .addCell(smallCell(expertApprove.getApproveAmount()))
                    .addCell(smallCell(expertApprove.getApproveRate()))
                    .addCell(smallCell(DateTimeUtil.format(expertApprove.getCreateTime()
                            ,NORM_DATETIME_PATTERN)));
        }
        document.add(expertAuditTable);
    }

    private static void createPhoneApproveModule(Document document, ApplicationPhoneApprove applicationPhoneApprove) {
        if (applicationPhoneApprove == null){
            return;
        }
        createInfoTableTitle(document,"电核信息");
        createIpcTableTitle(document,"审批信息");
        Table phoneApproveTable = createIpcTable();
        phoneApproveTable.addCell(smallNoBorderCell("电核员:"))
                .addCell(smallNoBorderCell(applicationPhoneApprove.getApproveUserName()));
        phoneApproveTable.addCell(smallNoBorderCell("电核时间:")).addCell(smallNoBorderCell(DateTimeUtil
                .format(applicationPhoneApprove.getApproveTime(),NORM_DATETIME_PATTERN)));
        phoneApproveTable.addCell(smallNoBorderCell("电核决定:")).addCell(smallNoBorderCell(Objects
                .equals(applicationPhoneApprove.getApproveResult(), PASS) ?"通过":"拒绝"));
        phoneApproveTable.addCell(smallNoBorderCell("备注:"))
                .addCell(smallNoBorderCell(applicationPhoneApprove.getRemark()));
        document.add(phoneApproveTable);

        if (applicationPhoneApprove.getIpcModifyInfoTree() == null
                || applicationPhoneApprove.getIpcModifyInfoTree().isEmpty()){
            return;
        }

        createIpcTableTitle(document,"电核修改信息");
        Table phoneApproveModifyHistoryTable = createSmallCustomCellTable(phoneApproveUnitValue);
        phoneApproveModifyHistoryTable.setHorizontalAlignment(HorizontalAlignment.CENTER);
        phoneApproveModifyHistoryTable.addCell(tableTitle("字段名"))
                .addCell(tableTitle("修改前")).addCell(tableTitle("修改后").add(tableTitle("修改时间")));
        List<ApplicationIPC> ipcModifyInfoTree = applicationPhoneApprove.getIpcModifyInfoTree();
        for (ApplicationIPC applicationIPC : ipcModifyInfoTree) {
            createIpcTableTitle(document,applicationIPC.getName());
            List<ApplicationIPC> childList = applicationIPC.getChildList();
            for (ApplicationIPC childIPC : childList) {
                List<ApplicationValueModifyHistory> applicationValueModifyHistoryList =
                        childIPC.getApplicationValueModifyHistoryList();
                String name = childIPC.getName();
                for (ApplicationValueModifyHistory modifyHistory : applicationValueModifyHistoryList) {
                    phoneApproveModifyHistoryTable
                            .addCell(smallCell(name))
                            .addCell(smallCell(modifyHistory.getBeforeValue()))
                            .addCell(smallCell(modifyHistory.getAfterValue()))
                            .addCell(smallCell(DateTimeUtil.format(modifyHistory.getModifyTime()
                                    ,NORM_DATETIME_PATTERN)));
                }
            }
        }
        document.add(phoneApproveModifyHistoryTable);
    }

    private static void createFinalIPCTable(List<ApplicationIPC> ipc,String title, Document document) {
        if (ipc == null || ipc.isEmpty()){
            return;
        }
        createInfoTableTitle(document,title+":");
        for (ApplicationIPC applicationIPC : ipc) {
            if(applicationIPC.getChildList().stream()
                    .allMatch(childIpc -> childIpc.getInputType() == 6 || childIpc.getInputType() == 7)){
                continue;
            }
            createIpcTableTitle(document,applicationIPC.getName());
            Table ipcTable = createIpcTable();
            for (ApplicationIPC childIPC : applicationIPC.getChildList()) {
                ipcTable.addCell(smallNoBorderCell(childIPC.getName()+":"))
                        .addCell(smallNoBorderCell(StringUtils.isBlank(childIPC.getApplicationValue())
                                ? "未填写" : childIPC.getApplicationValue()));
            }
            document.add(ipcTable);
        }
    }

    public static String getRepayment(Integer approveStatus){
        switch (approveStatus){
            case 0:
                return "等额本金";
            case 1:
                return "到期还本付息";
            case 2:
                return "等额本息";
            case 3:
                return "按月付息到期还本";
            default:
                return null;
        }
    }

    private static String getApproveStatus(Integer repayment){
        switch (repayment){
            case 0:
                return "待审批";
            case 1:
                return "通过";
            case 2:
                return "拒绝";
            default:
                return null;
        }
    }

    private static void createIpcTableTitle(Document document,String string) {
        Paragraph applyInfo = new Paragraph(new Text(string).addStyle(getBoldFont().setFontSize(11)));
        applyInfo.setMarginLeft(30f);
        document.add(applyInfo);
        Paragraph dashLine = createDottedLine(450);
        dashLine.setMarginLeft(30f);
        document.add(dashLine);
    }

    private static void createInfoTableTitle(Document document, String string) {
        Paragraph applyInfo = new Paragraph(new Text(string).addStyle(getBoldFont()));
        document.add(applyInfo);
        Paragraph line = createDottedLine(500);
        document.add(line);
    }

    private static Table createInfoTable(){
        return createTable(infoUnitValue);
    }

    private static Table createIpcTable(){
        return createSmallCustomCellTable(infoUnitValue);
    }

    private static Table createSmallCustomCellTable(UnitValue [] unitValues){
        return createTable(unitValues).setMarginLeft(30f).setMarginRight(30f).setMarginTop(5f);
    }

    private static Table createTable(UnitValue[] unitValues) {
        return new Table(unitValues).setWidthPercent(100);
    }

    private static Paragraph createDottedLine(int length) {
        DottedLine dottedLine = new DottedLine();
        dottedLine.setColor(new DeviceRgb());
        return new Paragraph().addTabStops(new TabStop(length, TabAlignment.LEFT,dottedLine)).add(new Tab());
    }

    private static Cell cell(Object object){
        return new Cell().add(obj2str(object));
    }

    private static Cell smallCell(Object object){
        return cell(object).setFontSize(10);
    }


    private static Cell noBorderCell(Object object){
        return cell(object).setBorder(Border.NO_BORDER);
    }

    private static Cell smallNoBorderCell(Object object){
        return noBorderCell(object).setFontSize(10);
    }

    private static String obj2str(Object object){
        return Optional.ofNullable(object).map(Object::toString).orElse("未填写");
    }
    private static Paragraph tableTitle(String string){
        return new Paragraph(string).addStyle(getBoldFont().setFontSize(10));
    }

    private static Style getBoldFont() {
        return new Style()
                .setFont(getPdfFont())
                .setFontSize(12)
                .setBold();
    }

    private static PdfFont getPdfFont() {
        try {
            return PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", false);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
